package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.repository.IStrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IStrategyTemplateSearchService;
import cn.wolfcode.luowowo.search.template.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyTemplateSearchServiceImpl implements IStrategyTemplateSearchService {

    @Autowired
    private IStrategyTemplateRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private TransportClient client;

    @Override
    public void saveOrUpdate(StrategyTemplate strategyTemplate) {
        repository.save(strategyTemplate);
    }

    @Override
    public List<Map<String, Object>> getThemeCommend() {

        List<Map<String, Object>> data = new ArrayList<>();

        //-----------查询出所有主题--------------
        //拼接聚合查询字段信息
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();

        //分组查询中: id这个key
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.missingBucket(true);  //忽略不满足条件bucket
        idSource.field("themeId");
        sources.add(idSource);

        //分组查询中: name这个key
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.missingBucket(true);  //忽略不满足条件bucket
        nameSource.field("themeName");
        sources.add(nameSource);

        //参数1:分组查询结果名称  参数2:分组查询字段配置对象集合
        CompositeAggregationBuilder aggsBuilder = new CompositeAggregationBuilder("themeGroup", sources);


        //发起查询请求操作
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withIndices(StrategyTemplate.INDEX_NAME); //查询的索引
        builder.withTypes(StrategyTemplate.TYPE_NAME);  //查询的类型
        builder.addAggregation(aggsBuilder);  //聚合查询构建模块

        //聚合查询结果
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());

        //分组查询结果对象: buckets 封装对象
        InternalComposite aggregation = page.getAggregations().get("themeGroup");

        List<StatisVO> themes = new ArrayList<>();
        //遍历buckets
        for (CompositeAggregation.Bucket bucket : aggregation.getBuckets()) {
            Map<String, Object> key = bucket.getKey();
            StatisVO vo = new StatisVO();
            vo.setId(Long.parseLong(key.get("id").toString()));
            vo.setName(key.get("name").toString());
            vo.setCount(bucket.getDocCount());
            themes.add(vo);
        }

        //第一个完善:排序  themes集合中通过DocCount排序,此处是倒序
        Collections.sort(themes, new Comparator<StatisVO>() {
            //返回结果是int类型
            //正数:表示大于
            //负数:表示小于
            // 0 :表示等于
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
                return Integer.valueOf((o2.getCount() - o1.getCount()) + "");
            }
        });

        //第二个完善: 截取前面10个
        List<StatisVO> subThemes = null;
        if (themes.size() > 10) {
            subThemes = themes.subList(0, 10);
        } else {
            subThemes = themes.subList(0, themes.size());
        }


        //--------------遍历所有主题查询该主题下所有目的地---------------------
        for (StatisVO theme : themes) {
            //通过主题id查询主题下的所有目的地集合
            List<StatisVO> dests = this.getDestByThemeId(theme.getId());

            //左边:主题vo  右边: 目的地集合(list<VO>)
            Map<String, Object> map = new HashMap<>();
            map.put("theme", theme);
            map.put("dests", dests);
            data.add(map);
        }

        return data;
    }

    @Override
    public List<StatisVO> queryConditionGroup(int type) {
        String idField = "";
        String nameField = "";
        BoolQueryBuilder query = null;

        //国外
        if (type == SearchQueryObject.CONDITION_TYPE_ABROAD) {
            idField = "countryId";
            nameField = "countryName";
            //需要排除中国
            query = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery("countryId", 1));
            //国内
        } else if (type == SearchQueryObject.CONDITION_TYPE_UN_ABROAD) {
            idField = "provinceId";
            nameField = "provinceName";
        } else if (type == SearchQueryObject.CONDITION_TYPE_THEME) {
            idField = "themeId";
            nameField = "themeName";
        }

        return this.statisGroup(idField, nameField, "conditionGroup",query);
    }

    @Override
    public List<StrategyTemplate> findByDestName(String name) {
        return repository.findByDestName(name);
    }

    @Override
    public Page query(SearchQueryObject qo) {

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if(qo.getType()==SearchQueryObject.CONDITION_TYPE_ABROAD){
            //海外  countryId
            boolQuery.must(QueryBuilders.termQuery("countryId", qo.getTypeValue()));
        }else if(qo.getType()==SearchQueryObject.CONDITION_TYPE_UN_ABROAD){
            //国内  provinceId
            boolQuery.must(QueryBuilders.termQuery("provinceId", qo.getTypeValue()));
        }else if(qo.getType()==SearchQueryObject.CONDITION_TYPE_THEME){
            //主题  themeId
            boolQuery.must(QueryBuilders.termQuery("themeId", qo.getTypeValue()));
        }
        return repository.search(boolQuery,qo.getPageable());
    }

    //根据不同条件封装查询
    private List<StatisVO> statisGroup(String idField, String nameField, String groupName, BoolQueryBuilder query) {
        //-----------查询出所有维度数据--------------
        //拼接聚合查询字段信息
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();

        //分组查询中: id这个key
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.missingBucket(true);  //忽略不满足条件bucket
        idSource.field(idField);
        sources.add(idSource);

        //分组查询中: name这个key
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.missingBucket(true);  //忽略不满足条件bucket
        nameSource.field(nameField);
        sources.add(nameSource);

        //参数1:分组查询结果名称  参数2:分组查询字段配置对象集合
        CompositeAggregationBuilder aggsBuilder = new CompositeAggregationBuilder(groupName, sources);

        //发起查询请求操作
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withIndices(StrategyTemplate.INDEX_NAME); //查询的索引
        builder.withTypes(StrategyTemplate.TYPE_NAME);  //查询的类型
        builder.addAggregation(aggsBuilder);  //聚合查询构建模块

        if(query!=null){
            builder.withQuery(query);
        }

        //聚合查询结果
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());

        //分组查询结果对象: buckets 封装对象
        InternalComposite aggregation = page.getAggregations().get(groupName);

        List<StatisVO> themes = new ArrayList<>();
        //遍历buckets
        for (CompositeAggregation.Bucket bucket : aggregation.getBuckets()) {
            Map<String, Object> key = bucket.getKey();

            if(key.get("id")==null || key.get("name") == null){
                continue;
            }
            StatisVO vo = new StatisVO();
            vo.setId(Long.parseLong(key.get("id").toString()));
            vo.setName(key.get("name").toString());
            vo.setCount(bucket.getDocCount());
            themes.add(vo);
        }
        //第一个完善:排序  themes集合中通过DocCount排序,此处是倒序
        Collections.sort(themes, new Comparator<StatisVO>() {
            //返回结果是int类型
            //正数:表示大于
            //负数:表示小于
            // 0 :表示等于
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
                return Integer.valueOf((o2.getCount() - o1.getCount()) + "");
            }
        });

        return themes;
    }

    private List<StatisVO> getDestByThemeId(Long themeId) {
        Iterable<StrategyTemplate> iterable = repository.search(QueryBuilders.termQuery("themeId", themeId));
        List<StatisVO> list = new ArrayList<>();

        //第三个完善:目的地去除重复
        List<String> temp = new ArrayList<>(); //放置已经存在的目的地名称
        iterable.forEach(st -> {

            //如果临时的list中不存在这个目的地名,执行添加操作
            if (!temp.contains(st.getDestName())) {
                StatisVO vo = new StatisVO();
                vo.setId(st.getDestId());
                vo.setName(st.getDestName());
                list.add(vo);

                //添加完成之后,临时list必须将该目的地名保存
                temp.add(st.getDestName());
            }
        });

        return list;
    }
}
